/* Copyright(C): Leaf Johnson 2009,2010

    This file is part of leaf-lib.

    leaf-lib is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    leaf-lib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with leaf-lib.  If not, see <http://www.gnu.org/licenses/>.


 * 
 * 
 */


#ifndef OSIFACE_H_INCLUDED
#define OSIFACE_H_INCLUDED
#include "leaf/base.h"
#include <avrx.h>
#include <avr/io.h>
#include <avr/interrupt.h>

/*+ 内核资源分配 **********************************************************************/
static inline void set_kernel_stack( void *sp )
{
	AvrXSetKernelStack( sp );
}

/*+ 中断控制与内核进出 ****************************************************************/
//保存现场，进入内核上下文
static inline void enter_kernel( void )
{
	IntProlog();
}
//回到任务上下文
static inline void enter_task( void )
{
	Epilog();
}
static inline void exit_kernel( void )
{
	Epilog();
}
/* 定义用于AvrX的中断服务程序，需要在中断服务程序的代码需要用enter_kernel(), exit_kernel()来包围
 * 即保存，恢复上下文 */
#define DEF_OSISR( intr ) \
	AVRX_SIGINT( intr )
/* 定义avr-gcc格式的中断服务程序，不需要添加enter_kernel, exit_kernel */
#define DEF_ISR( intr ) \
	ISR( intr )

/*+ 任务管理 *************************************************************************/
typedef TaskControlBlock	Task;/*TaskControlBlock实际上保存的是一个任务的静态描述*/
typedef pProcessID			Pid;/* pid是一进程的标识，所以定义为指针比较合理 */
typedef ProcessID			Process;/* ProcessID结构保存的是一个进程在运行中的信息 */

/* 声明一个任务，要求task是一个已经实现的函数 */
#define DECL_TASK( task, sz, prio )\
	AVRX_GCC_TASK( task, sz, prio )

/* 定义一个任务，使用方法见leaf-app中的范例任务 */
#define DEF_TASK( task, sz, prio ) \
	AVRX_GCC_TASKDEF( task, sz, prio )

/* 将一个任务声明为extern，即放于头文件的任务声明，使用方法见leaf-app/headers/tasks.h */
#define DECL_TASK_EXT( task ) \
	AVRX_EXTERNTASK( task )

#define __task( taskname ) (TCB(taskname))
#define __pid( taskname ) (PID(taskname))
/* 从任务名获得Task *的方法是__task(name),获得Pid的方法是__pid(name) */
/* 执行任务，参数是Task指针 */
static inline void execute( Task * task )
{
	AvrXRunTask( task );
}
/* 初始化任务，即装载而不运行 */
static inline void init_task( Task * task )
{
	AvrXInitTask( task );
}
/* 使任务开始执行 */
static inline void resume( Pid p )
{
	AvrXResume( p );
}
/* 使任务挂起 */
static inline void suspend( Pid p )
{
	AvrXSuspend( p );
}
/*方便的调用方法，其参数是任务名*/
#define load_task( tasknm ) init_task( __task(tasknm) )
#define execute_task( tasknm ) execute( __task(tasknm) )
#define resume_task( tasknm ) resume( __pid(tasknm) )
#define suspend_task( tasknm ) suspend( __pid(tasknm) )

/* 终结一个任务，不可恢复 */
static inline void kill( Pid p )
{
	AvrXTerminate( p );
}
/* 任务自我终结 */
static inline void task_exit( void )
{
	AvrXTaskExit();
}
/* 挂起系统，即系统不再执行任何功能 */
static inline void system_halt( void )
{
	AvrXHalt();
}
/* 查看任务优先级 */
static inline uint8_t task_get_prio( Pid p )
{
	return AvrXPriority( p );
}
/* 设置任务优先级 */
static inline uint8_t task_set_prio( Pid p, uint8_t prio )
{
	return AvrXChangePriority( p, prio );
}
/* 获取自身pid */
static inline Pid self( void )
{
	return AvrXSelf();
}
/* yield，即让出执行时间 */
void AvrXYield(void);
static inline void task_yield( void )
{
	AvrXYield();
}
/*+  信号量 *************************************************************************/
//typedef Mutex				Mutex;
//typedef	pMutex				pMutex;
static inline void set_mutex( pMutex m )
{
	AvrXSetSemaphore( m );
}
static inline void set_mutex_int( pMutex m )
{
	AvrXIntSetSemaphore( m );
}
static inline void wait_mutex( pMutex m )
{
	AvrXWaitSemaphore( m );
}
static inline Mutex test_mutex( pMutex m )
{
	return AvrXTestSemaphore( m );
}
static inline void reset_mutex( pMutex m )
{
	AvrXResetSemaphore( m );
}

/*+  定时系统 ***********************************************************************/
typedef TimerControlBlock	Timer;
typedef Timer *				pTimer;
typedef unsigned int		Ticks;

#define time_tick AvrXTimerHandler
static inline void start_timer( pTimer tmr, Ticks ticks )
{
	AvrXStartTimer( tmr, ticks );
}
static inline void wait_timer( pTimer tmr )
{
	AvrXWaitTimer( tmr );
}
/* 睡眠指定的系统节拍数，如果想使用人类时间单位的话，请使用devices/sysclk.h文件中的函数 */
static inline void sleep_ticks( pTimer tmr, Ticks ticks )
{
	AvrXDelay( tmr, ticks );
}

/*+ 消息系统 ************************************************************************/
typedef MessageQueue		MsgBox;
typedef pMessageQueue		pMsgBox;
typedef MessageControlBlock	Message, Msg;
typedef Message *			pMsg;
typedef TimerMessageBlock	TimerMsg;
typedef TimerMsg *			pTimerMsg;
/* 消息系统的使用概述：
 * 定义邮箱请使用MsgBox mb
 * 定义消息请使用Message msg;
 * !!注意消息和邮箱不能使用栈空间，即函数内的局部变量
 * 然后发消息使用send_msg( &mb, &msg );
 * 如果位于中断服务程序、或内核上下文中请使用send_msg_int
 * 会挂起等消息的操作是作用于邮箱的wait_msg( &mb );
 * 非挂起的检查操作请使用check_msg_box(&mb);
 * */
static inline void start_timer_msg( pMsgBox mb, TimerMsg *tm, unsigned delay )
{
	AvrXStartTimerMessage( tm, delay, mb );
}
static inline void cancel_timer_msg( pMsgBox mb, TimerMsg *tm )
{
	AvrXCancelTimerMessage( tm, mb );
}
static inline void send_msg_int( pMsgBox mb, pMsg m )
{
	AvrXIntSendMessage( mb, m );
}
static inline void send_msg( pMsgBox mb, pMsg m )
{
	AvrXSendMessage( mb, m );
}
static inline pMsg wait_msg( pMsgBox mb )
{
	return AvrXWaitMessage( mb );
}
static inline pMsg check_msg_box( pMsgBox mb )
{
	return AvrXRecvMessage( mb );
}
static inline void ack_msg( pMsg m )
{
	AvrXAckMessage( m );
}
static inline void wait_msg_ack( pMsg m )
{
	AvrXWaitMessageAck( m );
}
static inline Mutex test_msg_ack( pMsg m )
{
	return AvrXTestMessageAck( m );
}

/*+ System Message Utility */
/* System Message的使用请参考doucments/sysmsg.txt */
typedef union{
	void *p;
	int val;
}SysMsgData;
typedef struct{
	Message mcb;
	uint8_t id;
	union{
		void *p;
		int val;
	}data;
}SysMsg, *pSysMsg;
static inline void send_sys_msg( pMsgBox mb, pSysMsg msg )
{
	send_msg( mb, (pMsg)msg );
}
static inline void send_sys_msg_int( pMsgBox mb, pSysMsg msg )
{
	send_msg_int( mb, (pMsg)msg );
}
static inline pSysMsg wait_sys_msg( pMsgBox mb )
{
	return ( pSysMsg )wait_msg( mb );
}
static inline void wait_sys_msg_ack( pSysMsg m )
{
	wait_msg_ack( &m->mcb );
}
static inline void ack_sys_msg( pSysMsg m )
{
	ack_msg( &m->mcb );
}
typedef void ( * SysMsgHandler ) ( pSysMsg );
typedef void ( * TimeoutHandler )( void );
#endif /* OSIFACE_H_INCLUDED */
